package com.itheima.consumer;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * <dl>
 * <dd>描述: ~节点业务逻辑实现</dd>
 * <dd>创建时间：  10:10 2020/7/27</dd>
 * <dd>创建人： zz</dd>
 * <dt>版本历史: </dt>
 * <pre>
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2020/7/27      guodong       1.0        1.0 Version
 * </pre>
 * </dl>
 */
@Component
@RabbitListener(queues = "order.A") //指定监听队列名称
@Slf4j
public class OrderConsumer {

    /*
        channel: 信道，通过此对象可以手动确认消息
        deliveryTag：信道中标识消息索引位置
        redeliveryTag：标识消息是否重回过队列，如果消息重回过队列值为true
     */
    @RabbitHandler //转换
    public void orderMsg(String msg, Channel channel,
                         @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
                         @Header(AmqpHeaders.REDELIVERED) boolean redeliveryTag){
        try {//消息消费成功
            log.info("deliveryTag: {} ， redeliveryTag： {}" ,deliveryTag ,redeliveryTag);
            if(msg.contains("苹果")){
                throw new RuntimeException("不许购买苹果产品，请选择国产机...");
            }
            //为了测试限流所以让模拟休息5s
            Thread.sleep(5000);
            log.info("下单消息: {}", msg);
            //multiple: 代表是否批量删除的意思
            //调用ack发送消息确认将消息从队列中移除
            channel.basicAck(deliveryTag,false);
        }catch (Exception e){//消息消费失败
            //2.redeliveryTag
            if(redeliveryTag){ //表示消息重回过队列，将消息移除
                try {
                    log.info("消息重回过队列，并且再次消费失败，将其移除： redeliveryTag： {}", redeliveryTag);
                    channel.basicNack(deliveryTag, false, false);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }else {
                try {
                    log.info("消息第一次消费失败，将其重回队列");
                    //调用basicNack方法：第三个参数代表是否重回队列，如果为true则表示消息重回队列
                    channel.basicNack(deliveryTag, false, true);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}
